import time
import wx
import vtk
import math
import numpy
import vtktudoss
import os, sys

try:
    import extended.BaseCalc as BaseCalc
except ImportError:
    import BaseCalc

#~ [wxID1] = [wx.NewId() for __init__ in range(1)]
    
def create(parent, renderwindow, primaryrenderer):
    return WidgetOverlay(parent, renderwindow, primaryrenderer)
    
class WidgetOverlay:
    def __init__(self, parent, renderwindow, primaryrenderer):
        print "WidgetOverlay module loaded."        
        self.parent = parent
        self.renderwindow = renderwindow.GetRenderWindow()
        self.interactorstyle = renderwindow.GetInteractorStyle()
        self.renX = primaryrenderer
        self.baseCalc = BaseCalc.create(self, self)
        self.windowsize = renderwindow.GetSize()
        
        self.delayRegeneration = False
        #~ self.Bind(wx.EVT_RIGHT_DCLICK, self.OnRightClick, mitem)
              
        self.InitializeAnnotationLayer()
        self.InitializeSubdrawLayer()
        self.FillOverlay()

    def InitializeAnnotationLayer(self):
        try:
            self.renderwindow.RemoveRenderer(self.renXannotation)
        except AttributeError:
            pass
        self.renderwindow.SetNumberOfLayers(2)
        self.renXannotation = vtk.vtkRenderer()
        self.renX.SetLayer(1)
        self.renXannotation.SetLayer(2)
        self.renXannotation.InteractiveOff()
        self.renXannotation.SetActiveCamera(self.renX.GetActiveCamera())
        self.renderwindow.AddRenderer(self.renXannotation)
        
    def InitializeSubdrawLayer(self):
        try:
            self.renderwindow.RemoveRenderer(self.renXsubdraw)
        except AttributeError:
            pass
        self.renderwindow.SetNumberOfLayers(3)
        self.renXsubdraw = vtk.vtkRenderer()
        self.renXsubdraw.SetLayer(0)
        self.renXsubdraw.SetBackground([0.3, 0.3, 0.3])
        self.renXsubdraw.InteractiveOff()
        self.renXsubdraw.SetActiveCamera(self.renX.GetActiveCamera())
        self.renderwindow.AddRenderer(self.renXsubdraw)
        
        reader = vtk.vtkSTLReader()
        fname = os.path.join(self.parent.appdir, 'torso_shell.stl')
        reader.SetFileName(fname)
        output = reader.GetOutput()
        Normals = vtk.vtkPolyDataNormals()
        Normals.SetInput(output)#.GetOutput())
        Normals.SplittingOff()
        Normals.ConsistencyOff()
        TriangleFilter = vtk.vtkTriangleFilter()
        TriangleFilter.SetInput(Normals.GetOutput())
        TriangleFilter.Update()
        torsimapper = vtk.vtkPolyDataMapper()
        torsimapper.SetInput(TriangleFilter.GetOutput())
        self.torsiactor = vtk.vtkActor()
        self.torsiactor.SetMapper(torsimapper)
        #~ self.torsiactor.SetPosition(0, -0.7, 0)
        #self.torsiactor.GetProperty().SetDiffuseColor(0.6, 0.6, 0.6)
        #self.torsiactor.GetProperty().SetDiffuseColor(1.6, 0.6, 0.6)
        self.torsiactor.GetProperty().SetDiffuse(0)
        self.torsiactor.GetProperty().SetAmbientColor(0.0, 0.0, 0.0)
        self.torsiactor.GetProperty().SetAmbient(1.0)
        self.renXsubdraw.AddActor(self.torsiactor)

    def FillOverlay(self):
        #~ sph = vtk.vtkSphereSource()
        #~ sph.SetPhiResolution(32)
        #~ sph.SetThetaResolution(32)
        #~ sph.SetRadius(0.1)
        
        stlreader = vtk.vtkSTLReader()
        stlreader.SetFileName("jointnudge.stl")
        stlreader.Update()
        
        t = vtk.vtkTransform()
        t.Scale([10, 10, 10])
        #~ t.RotateX(90)
        #~ t.Translate(7,20,-15) 
        t.Update()
        tf = vtk.vtkTransformFilter()
        tf.SetTransform(t)
        tf.SetInput(stlreader.GetOutput())
        
        normalout = vtk.vtkPolyDataNormals()
        normalout.SetInput(tf.GetOutput())
        normalout.SetFeatureAngle(60.0)
        sph = normalout
        
        offset = 0.8
        
        #spine
        spinemap = vtk.vtkPolyDataMapper()
        self.spineact = vtk.vtkActor()
        self.spineact.SetMapper(spinemap)
        self.spineact.GetProperty().SetColor(1.0, 1.0, 0.0)
        spinemap.SetInput(sph.GetOutput())
        self.spineact.SetPosition(0, 1.73, 9.615)#offset,1,1.4)
        self.renXannotation.AddActor(self.spineact)
        #~ self.parent.cellpicker.AddPickList(self.spineact)
        
        #clavicle
        clavmap = vtk.vtkPolyDataMapper()
        self.clavact = vtk.vtkActor()
        self.clavact.GetProperty().SetColor(0.0, 1.0, 1.0)
        self.clavact.SetMapper(clavmap)
        clavmap.SetInput(sph.GetOutput())
        self.clavact.SetPosition(-3.531, 3.594, 23.757)#offset - 0.2,-0.1,1.5)
        self.renXannotation.AddActor(self.clavact)
        #~ self.parent.cellpicker.AddPickList(self.clavact)
    
        #scapula
        scapmap = vtk.vtkPolyDataMapper()
        self.scapact = vtk.vtkActor()
        self.scapact.SetMapper(scapmap)
        self.scapact.GetProperty().SetColor(0.0, 1.0, 0.0)
        scapmap.SetInput(sph.GetOutput())
        self.scapact.SetPosition(4.441, 7.518, 25.701)#offset + 0.4,-0.2,1.75)
        self.renXannotation.AddActor(self.scapact)
        #~ self.parent.cellpicker.AddPickList(self.scapact)
    
        #GH
        ghmap = vtk.vtkPolyDataMapper()
        self.GHact = vtk.vtkActor()
        self.GHact.SetMapper(ghmap)
        self.GHact.GetProperty().SetColor(1.0, 0.0, 1.0)
        ghmap.SetInput(sph.GetOutput())
        self.GHact.SetPosition(1.583, 10.187, 22.778)#offset + 0.2,0,1.9)
        self.renXannotation.AddActor(self.GHact)
        #~ self.parent.cellpicker.AddPickList(self.GHact)
        
        #EL
        ELmap = vtk.vtkPolyDataMapper()
        self.ELact = vtk.vtkActor()
        self.ELact.GetProperty().SetColor(1.0, 0.0, 0.0)
        self.ELact.SetMapper(ELmap)
        ELmap.SetInput(sph.GetOutput())
        self.ELact.SetPosition(2.188, 20.051, 21.824)#offset + 0.17, -0.13, 3.0)
        self.renXannotation.AddActor(self.ELact)
        #~ self.parent.cellpicker.AddPickList(self.ELact)
        
        wristpos = (2.942, 32.59, 22.129)#offset -0.1, -0.13, 4.0)
        
        self.GHGlobal = vtk.vtkActor()
        
        #SpanLines
        linelength = 2.0
        verticalPoints = vtk.vtkPoints()
        verticalPoints.SetNumberOfPoints(6)
        verticalPoints.InsertPoint(0, self.spineact.GetPosition())
        verticalPoints.InsertPoint(1, self.clavact.GetPosition())
        verticalPoints.InsertPoint(2, self.scapact.GetPosition())
        verticalPoints.InsertPoint(3, self.GHact.GetPosition())
        verticalPoints.InsertPoint(4, self.ELact.GetPosition())
        verticalPoints.InsertPoint(5, wristpos)
        verticalLines = vtk.vtkCellArray()
        for i in range(0,5):
            verticalLines.InsertNextCell(2)		
            verticalLines.InsertCellPoint(i)
            verticalLines.InsertCellPoint(i+1)        
        verticalGuideline = vtk.vtkPolyData()
        verticalGuideline.SetLines(verticalLines)	
        verticalGuideline.SetPoints(verticalPoints)
        verticalGuideline.Update()
        
        profileTubes = vtk.vtkTubeFilter()
        profileTubes.SetNumberOfSides(12)
        profileTubes.SetInput(verticalGuideline)
        profileTubes.SetRadius(.1)
        #~ self.TubeMapper = vtk.vtkPolyDataMapper()            
        #~ self.TubeActor.SetMapper(self.TubeMapper)
        #~ self.TubeActor.GetProperty().SetAmbient(1.0)
        #~ self.TubeMapper.SetInput(profileTubes.GetOutput())
        
        Linemap = vtk.vtkPolyDataMapper()
        Lineact = vtk.vtkActor()
        Lineact.SetMapper(Linemap)
        Lineact.GetProperty().SetDiffuse(0)
        Lineact.GetProperty().SetAmbientColor(0,0,0.4)
        Lineact.GetProperty().SetAmbient(1)
        Linemap.SetInput(profileTubes.GetOutput())
        self.renXannotation.AddActor(Lineact)
        

    
    def ShowMenu(self, act):
        self.selectedJoint = act
        if self.selectedJoint == self.spineact:
            keyword = 'Thorax'
        elif self.selectedJoint == self.clavact:
            keyword = 'Clavicle'
        elif self.selectedJoint == self.scapact:
            keyword = 'Scapula'
        elif self.selectedJoint == self.GHact:
            keyword = 'Humerus'
        elif self.selectedJoint == self.ELact:
            keyword = 'Elbow'
            
        jAngles = self.parent.parent.Filters.jointAngleCollection
        Filters = self.parent.parent.Filters
        
        menuFiltersAdd = wx.Menu()
        for i in jAngles:            
            verhaal = i['description']
            verhaal = verhaal.replace('\n', ' ')
            if verhaal.find(keyword) != -1:
                tmpid = wx.NewId()
                menuFiltersAdd.Append(id = tmpid, text=verhaal)
                self.parent.Bind(wx.EVT_MENU,  lambda evt, temp=verhaal,\
                                            adding=1: self.OnMenuFilters(evt, temp, adding), id = tmpid )  
                             
        menuFiltersRemove = wx.Menu()        
        nr_of_filters = len(Filters.filteredAngles)
        for i in jAngles:            
            verhaal = i['description']
            verhaal = verhaal.replace('\n', ' ')
            if verhaal.find(keyword) != -1:
                for j in range(0, nr_of_filters):
                    if Filters.filteredAngles[j] == i['stanceID']:
                        tmpid = wx.NewId()
                        menuFiltersRemove.Append(id = tmpid, text=verhaal)
                        self.parent.Bind(wx.EVT_MENU,  lambda evt, temp=verhaal,\
                                                    adding=0: self.OnMenuFilters(evt, temp, adding), id = tmpid )
        tmpid = wx.NewId()
        menuFiltersRemove.Append(id = tmpid, text='All')
        self.parent.Bind(wx.EVT_MENU, self.OnMenuRemoveAllFilters, id = tmpid)       
                                                    
        menuPlotAdd = wx.Menu()
        for i in jAngles:            
            verhaal = i['description']
            verhaal = verhaal.replace('\n', ' ')
            if verhaal.find(keyword) != -1:
                tmpid = wx.NewId()
                menuPlotAdd.Append(id = tmpid, text=verhaal)
                self.parent.Bind(wx.EVT_MENU,  lambda evt, temp=verhaal,\
                                            adding=1: self.OnMenuPlot(evt, temp, adding), id = tmpid )  
                             
        menuPlotRemove = wx.Menu()        
        nr_of_plots = len(Filters.plottedAngles)
        for i in jAngles:            
            verhaal = i['description']
            verhaal = verhaal.replace('\n', ' ')
            if verhaal.find(keyword) != -1:
                for j in range(0, nr_of_plots):
                    if Filters.plottedAngles[j] == i['stanceID']:
                        tmpid = wx.NewId()
                        menuPlotRemove.Append(id = tmpid, text=verhaal)
                        self.parent.Bind(wx.EVT_MENU,  lambda evt, temp=verhaal,\
                                                    adding=0: self.OnMenuPlot(evt, temp, adding), id = tmpid )  
        tmpid = wx.NewId()
        menuPlotRemove.Append(id = tmpid, text='All')
        self.parent.Bind(wx.EVT_MENU, self.OnMenuRemoveAllPlot, id = tmpid)        
        
        
        menuBothAdd = wx.Menu()
        for i in jAngles:            
            verhaal = i['description']
            verhaal = verhaal.replace('\n', ' ')
            if verhaal.find(keyword) != -1:
                tmpid = wx.NewId()
                menuBothAdd.Append(id = tmpid, text=verhaal)
                self.parent.Bind(wx.EVT_MENU,  lambda evt, temp=verhaal,\
                                            adding=1: self.OnMenuBoth(evt, temp, adding), id = tmpid )  
                             
        menuBothRemove = wx.Menu()        
        nr_of_filters = len(Filters.filteredAngles)
        nr_of_plots = len(Filters.plottedAngles)
        for i in jAngles:            
            verhaal = i['description']
            verhaal = verhaal.replace('\n', ' ')
            if verhaal.find(keyword) != -1:
                already_added = False
                for j in range(0, nr_of_filters):                    
                    if Filters.filteredAngles[j] == i['stanceID']:
                        tmpid = wx.NewId()
                        menuBothRemove.Append(id = tmpid, text=verhaal)
                        self.parent.Bind(wx.EVT_MENU,  lambda evt, temp=verhaal,\
                                                    adding=0: self.OnMenuBoth(evt, temp, adding), id = tmpid )
                        already_added = True
                if not already_added:
                    for j in range(0, nr_of_plots):
                        if Filters.plottedAngles[j] == i['stanceID']:
                            tmpid = wx.NewId()
                            menuBothRemove.Append(id = tmpid, text=verhaal)
                            self.parent.Bind(wx.EVT_MENU,  lambda evt, temp=verhaal,\
                                                        adding=0: self.OnMenuBoth(evt, temp, adding), id = tmpid )
        tmpid = wx.NewId()
        menuBothRemove.Append(id = tmpid, text='All')
        self.parent.Bind(wx.EVT_MENU, self.OnMenuRemoveAllBoth, id = tmpid)
        
        
        menuFilters = wx.Menu()    
        menuFilters.AppendSubMenu(submenu=menuFiltersAdd, text='Add')
        menuFilters.AppendSubMenu(submenu=menuFiltersRemove, text='Remove')

        menuPlot = wx.Menu()    
        menuPlot.AppendSubMenu(submenu=menuPlotAdd, text='Add')
        menuPlot.AppendSubMenu(submenu=menuPlotRemove, text='Remove')
        
        menuBoth = wx.Menu()    
        menuBoth.AppendSubMenu(submenu=menuBothAdd, text='Add')
        menuBoth.AppendSubMenu(submenu=menuBothRemove, text='Remove')
        
        menu4 = wx.Menu()
        menu4.AppendSubMenu(submenu=menuFilters, text='Filter')
        menu4.AppendSubMenu(submenu=menuPlot, text='Plot')
        menu4.AppendSubMenu(submenu=menuBoth, text='Filter and Plot')
        
        mouseposition = wx.GetMousePosition()
        self.parent.PopupMenu( menu4, (mouseposition[0], mouseposition[1] - 48))
        menu4.Destroy()
 
    def OnMenuFilters(self, event, descript, adding):
        jAngles = self.parent.parent.Filters.jointAngleCollection
        for i in range(0, len(jAngles)):
            verhaal = jAngles[i]['description']
            verhaal = verhaal.replace('\n', ' ')
            if verhaal == descript:
                stanceID = jAngles[i]['stanceID']
                if adding:                    
                    self.OnAddFilter(stanceID)
                else:
                    self.OnRemoveFilter(stanceID)

    def OnMenuPlot(self, event, descript, adding):
        jAngles = self.parent.parent.Filters.jointAngleCollection
        for i in range(0, len(jAngles)):
            verhaal = jAngles[i]['description']
            verhaal = verhaal.replace('\n', ' ')
            if verhaal == descript:
                stanceID = jAngles[i]['stanceID']
                if adding:                    
                    self.OnAddPlot(stanceID)
                else:
                    self.OnRemovePlot(stanceID)
    
    def OnMenuBoth(self, event, descript, adding):
        self.OnMenuFilters(event, descript, adding)
        self.OnMenuPlot(event, descript, adding)
        
    def OnMenuRemoveAllBoth(self, event):
        self.OnMenuRemoveAllFilters(event)
        self.OnMenuRemoveAllPlot(event)

    def OnMenuRemoveAllFilters(self, event):
        self.delayRegeneration = True
        for i in range(0, 18):
            self.OnRemoveFilter(i)
        self.delayRegeneration = False
        self.OnRemoveFilter(-1)
        
    def OnMenuRemoveAllPlot(self, event):
        self.delayRegeneration = True
        for i in range(0, 18):
            self.OnRemovePlot(i)
        self.delayRegeneration = False
        self.OnRemovePlot(-1)
        
    
    def OnAddFilter(self, stanceID):
        Filters = self.parent.parent.Filters
        for filter in Filters.jointAngleCollection:
            if filter['stanceID'] == stanceID:
                Filters.filteredAngles.append(filter['stanceID'])
                filter['widget'].EnabledOn()
                self.parent.widgets.UpdateWidgets()
        self.parent.Render()   

    def OnAddPlot(self, stanceID):
        Filters = self.parent.parent.Filters
        for filter in Filters.jointAngleCollection:
            if filter['stanceID'] == stanceID:
                Filters.plottedAngles.append(filter['stanceID'])
        self.parent.parent.RegenerateSplineObjects()
        self.parent.ren3overlay.RefreshOverlay()        
        self.parent.Render()  
        
    def OnRemoveFilter(self, stanceID):
        Filters = self.parent.parent.Filters
        nr_of_plots = len(Filters.filteredAngles)
        for i in range(0, nr_of_plots):
            j = nr_of_plots - i - 1
            if Filters.filteredAngles[j] == stanceID or stanceID==-1:
                Filters.jointAngleCollection[Filters.filteredAngles[j]]['widget'].EnabledOff()
                Filters.filteredAngles.pop(j)                
                self.parent.widgets.UpdateWidgets()
        if not self.delayRegeneration:
            self.parent.parent.Filters.RestartFiltering()
            self.parent.Render()
            
    def OnRemovePlot(self, stanceID):
        Filters = self.parent.parent.Filters
        nr_of_plots = len(Filters.plottedAngles)
        for i in range(0, nr_of_plots):
            j = nr_of_plots - i - 1
            if Filters.plottedAngles[j] == stanceID or stanceID==-1:
                Filters.plottedAngles.pop(j)                
        if not self.delayRegeneration:
            self.parent.parent.RegenerateSplineObjects()        
            self.parent.ren3overlay.RefreshOverlay()        
            self.parent.Render()
    
    
    
    
    
    
    
    